package com.topsec.manager.util;


import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import org.apache.commons.lang.StringUtils;

import java.io.IOException;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JsonUtil {

    private static Gson gson = null;

    static {
        GsonBuilder builder = new GsonBuilder()
                .serializeNulls().setDateFormat("yyyy-MM-dd HH:mm:ss");
        builder.registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory());
        gson = builder.create();
    }

    public static String json(Object obj) {

        return getJson().toJson(obj);
    }


    public static <T> T unjson(String json, Class<T> z) {
        return getJson().fromJson(json, z);
    }

    public static <T> T unjson2(String json, Type v) {
        return getJson().fromJson(json, v);
    }

    public static Gson getJson() {

        return gson;
    }

    public static class NullStringToEmptyAdapterFactory<T> implements TypeAdapterFactory {

        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {

            Class<T> rawType = (Class<T>) type.getRawType();
            if (rawType == String.class) {
                return (TypeAdapter<T>) new StringAdapter();
            }
            if (rawType == Long.class) {
                return (TypeAdapter<T>) new LongAdapter();
            }
            if (rawType == Double.class) {
                return (TypeAdapter<T>) new DoubleAdapter();
            }
            if (rawType == Date.class) {
                return (TypeAdapter<T>) new DateAdapter();
            }
            return null;
        }
    }

    public static class DateAdapter extends TypeAdapter<Date> {
        public Date read(JsonReader reader) throws IOException {

            if (reader.peek() == JsonToken.STRING) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                try {
                    String str = reader.nextString();
                    if (StringUtils.isNotEmpty(str)) {
                        return simpleDateFormat.parse(str);
                    } else {
                        return null;
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            return null;
			/*try {
				return (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse((reader.nextString())));
			} catch (ParseException e) {
				e.printStackTrace();
			}
			return new Date();*/
        }

        public void write(JsonWriter writer, Date value) throws IOException {

            if (value == null || ("").equals(value)) {
                writer.value("");
            } else {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String format = simpleDateFormat.format(value);
                writer.value(format);
            }
        }
    }

    public static class StringAdapter extends TypeAdapter<String> {

        public String read(JsonReader reader) throws IOException {

            if (reader.peek() == JsonToken.NULL) {
                reader.nextNull();
                return null;
            }
            return reader.nextString();
        }

        public void write(JsonWriter writer, String value) throws IOException {

            if (value == null || "null".equalsIgnoreCase(value)) {
                writer.value("");
            } else {
                writer.value(value);
            }
        }
    }

    public static class LongAdapter extends TypeAdapter<Long> {

        public Long read(JsonReader reader) throws IOException {

            if (reader.peek() == JsonToken.NULL) {
                reader.nextNull();
                return null;
            }
            return reader.nextLong();
        }

        public void write(JsonWriter writer, Long value) throws IOException {

            if (value == null) {
                writer.value(0);
            } else {
                writer.value(value);
            }
        }
    }

    public static class DoubleAdapter extends TypeAdapter<Double> {

        public Double read(JsonReader reader) throws IOException {

            if (reader.peek() == JsonToken.NULL) {
                reader.nextNull();
                return null;
            }
            return reader.nextDouble();
        }

        public void write(JsonWriter writer, Double value) throws IOException {

            if (value == null) {
                writer.value(0);
            } else {
                writer.value(value);
            }
        }
    }

}
